﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Meraz.Core.Model;
using Meraz.Core.Repositories;
using Ninject;
using System.Diagnostics;
using Meraz.Core.Data;

namespace Meraz.Core.Commands
{
    public interface ICreateTweetCommand
    {
        ITweetRepository TweetRepository { get; set; }
        ITwitterTagRepository TwitterTagRepository { get; set; }
        ITwitterLinkRepository TwitterLinkRepository { get; set; }
        ITwitterMentionRepository TwitterMentionRepository { get; set; }
        ITwitterUserRepository TwitterUserRepository { get; set; }
        TweetValues Values { get; set; }
        Tweet Execute();
    }
    public class CreateTweetCommand : BaseCommand, ICreateTweetCommand
    {
        #region Properties
        [Inject]
        public ITweetRepository TweetRepository { get; set; }

        [Inject]
        public ITwitterTagRepository TwitterTagRepository { get; set; }

        [Inject]
        public ITwitterLinkRepository TwitterLinkRepository { get; set; }

        [Inject]
        public ITwitterMentionRepository TwitterMentionRepository { get; set; }

        [Inject]
        public ITwitterUserRepository TwitterUserRepository { get; set; }

        [Inject]
        public ICreateUrlRedirectCommand CreateUrlRedirectCommand { get; set; }

        [Inject]
        public ICreateDomainsCommand CreateDomainsCommand { get; set; }

        [Inject]
        public ICreateUrlsCommand CreateUrlsCommand { get; set; }

        public TweetValues Values { get; set; }

        #endregion
        public CreateTweetCommand() { }
        public CreateTweetCommand(TweetValues values) { this.Values = values; }

        public Tweet Execute()
        {
            int seq = 0;
            //if the tweet already exists, we'll do an update


            Tweet tweet = TweetRepository.GetById(Values.TweetID);
            if (tweet == null)
            {
                tweet = new Tweet();
                TweetRepository.Add(tweet);
                tweet.ID = Values.TweetID;
            }

            //TODO: why must I set the ClientID instead of the Client obj?
            tweet.ClientID = Values.Client.ID;
            tweet.Text = Values.Text;
            tweet.UserID = Values.UserID;
            tweet.Username = Values.Username;
            tweet.Pubdate = Values.Pubdate;
            tweet.StatusType = StatusType.New;
            tweet.InReplyToScreenName = Values.InReplyToScreenName;
            long inReplyToStatusID;
            if(Int64.TryParse(Values.InReplyToStatusID, out inReplyToStatusID))
                tweet.InReplyToStatusID = inReplyToStatusID;
            long inReplyToUserID;
            if (Int64.TryParse(Values.InReplyToUserID, out inReplyToUserID))
                tweet.InReplyToUserID = inReplyToUserID;
            bool retweeted;
            if (Boolean.TryParse(Values.Retweeted, out retweeted))
                tweet.IsRetweeted = retweeted;
            Commit();
            while (tweet.HasMentions)
            {
                TwitterMention oldMention = tweet.Mentions.Last();
                tweet.Mentions.Remove(oldMention);
                TwitterMentionRepository.Delete(oldMention);
            }
            Commit();

            foreach (TwitterMention mention in Values.Mentions)
            {
                TwitterMentionRepository.Add(mention);
                tweet.Mentions.Add(mention);
            }

            while (tweet.HasTags)
            {
                TwitterTag oldTag = tweet.Tags.Last();
                tweet.Tags.Remove(oldTag);
                TwitterTagRepository.Delete(oldTag);
            }
            Commit();
            tweet.Tags = new List<TwitterTag>();
            seq = 0;
            foreach (string tagName in Values.Tags)
            {
                TwitterTag tag = new TwitterTag(Values.TweetID, ++seq, tagName);
                TwitterTagRepository.Add(tag);
                tweet.Tags.Add(tag);
            }
            Commit();

            Dictionary<string, string> tones = new Dictionary<string, string>();
            while (tweet.HasLinks)
            {
                TwitterLink oldLink = tweet.Links.Last();
                int index = Values.Links.IndexOf(oldLink.Original);
                if (index > -1)
                {
                    tones[oldLink.Original] = oldLink.ToneType.ToString();
                }
                tweet.Links.Remove(oldLink);
                TwitterLinkRepository.Delete(oldLink);
            }
            Commit();

            //first save child records
            foreach (string urlstring in Values.Links)
            {
                if (string.IsNullOrWhiteSpace(urlstring))
                    continue;
                Domain domain = null;
                Url url = null;
                bool isError = false;
                CreateUrlRedirectCommand.Execute(urlstring);
                if (CreateUrlRedirectCommand.Status == System.Net.HttpStatusCode.OK)
                {
                    string redirect = CreateUrlRedirectCommand.Redirect;
                    domain = CreateDomainsCommand.Execute(redirect);
                    url = CreateUrlsCommand.Execute(redirect, domain);
                }
                else
                {
                    isError = true;
                    domain = CreateDomainsCommand.Execute(urlstring);
                    url = CreateUrlsCommand.Execute(urlstring, domain);
                }

                string tone = (tones.ContainsKey(urlstring)) ? tones[urlstring] :  ToneType.Neutral.ToString();
                if ((url != null) && (url.ID > 0))
                    MerazContext.Instance.CreateTwitterLink(Values.TweetID, url.ID, ++seq, urlstring, tone, isError);
            }

            return tweet;
        }
        protected override void Commit()
        {
            MerazContext.Instance.SaveAndAccept();
        }
    }
}
